// =====================================================
// ZMachine.NET / Jason Follas 
// Modified March 2007 by James Ashley
// =====================================================
using System;
using System.Collections.Generic;
using System.Text;
using ZMachine;
using System.Runtime.Serialization.Formatters.Binary;

namespace SophiaBot
{
    public class SAPIZMachine: VirtualMachine
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="SAPIZMachine"/> class.
        /// </summary>
        public SAPIZMachine()
        {
        }

        public delegate void SerializeHandler(
            Guid token, byte[] objectBytes, string statusXML);
        public SerializeHandler OnSerialize = null;
        public delegate byte[] DeserializeHandler(Guid token);
        public DeserializeHandler OnDeserialize = null;
        public delegate void OnQuitHandler();
        public event OnQuitHandler OnQuit;



        /// <summary>
        /// Gets the game lexicon.
        /// </summary>
        /// <value>The game lexicon.</value>
        public ZMachine.ZDictionary GameLexicon
        {
            get { return z_processor.Lexicon; }
        }

        /// <summary>
        /// Gets the output.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns></returns>
        public override string GetOutput(string input)
        {
            return z_processor.GetOutput(input);
        }

        /// <summary>
        /// Gets the status.
        /// </summary>
        /// <returns></returns>
        public override string GetStatus()
        {
            ZStatus status = z_processor.GetStatus();

            return "Location: " + status.Location +
                ".   Score: " + status.Num1.ToString() +
                ".   Moves: " + status.Num2.ToString() + ".";
        }

        /// <summary>
        /// Z_processor_s the on quit.
        /// </summary>
        protected void z_processor_OnQuit()
        {
            if (null != OnQuit)
                OnQuit();
        }

        internal protected void Stop()
        {
            z_processor.Stop();
        }

        /// <summary>
        /// Z_processor_s the on save.
        /// </summary>
        protected override void z_processor_OnSave()
        {
            Serialize();
        }

        /// <summary>
        /// Serializes this instance.
        /// </summary>
        protected override void Serialize()
        {
            if (OnSerialize != null)
            {
                UnwireEvents();

                BinaryFormatter bf = new BinaryFormatter();
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                bf.Serialize(ms, z_processor);
                bf = null;

                WireEvents();

                OnSerialize(m_ticket, ms.ToArray(), GetStatus());
            }
        }

        /// <summary>
        /// Z_processor_s the on restore.
        /// </summary>
        protected override void z_processor_OnRestore()
        {
            Deserialize();
        }

        /// <summary>
        /// Deserializes this instance.
        /// </summary>
        protected override void Deserialize()
        {
            if (OnDeserialize != null)
            {
                UnwireEvents();

                System.IO.MemoryStream ms = new System.IO.MemoryStream(OnDeserialize(m_ticket));

                BinaryFormatter bf = new BinaryFormatter();
                if(ms.Length > 0)
                z_processor = bf.Deserialize(ms) as ZProcessor;
                
                WireEvents();
            }
        }

        /// <summary>
        /// Wires the events.
        /// </summary>
        protected override void WireEvents()
        {
            z_processor.OnQuit += new ZProcessor.QuitHandler(z_processor_OnQuit);
            base.WireEvents();
        }

        /// <summary>
        /// Unwires the events.
        /// </summary>
        protected override void UnwireEvents()
        {
            base.UnwireEvents();
            z_processor.OnQuit -= new ZProcessor.QuitHandler(z_processor_OnQuit);
        }
    }
}
